#!/usr/bin/env python -OO
# -*- coding: utf-8 -*-

# Copyright © 2008,2009 Trust Digital Technology Laboratory, Shanghai Jiao Tong University.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Author:
#   XING Dong sheng <homer.xing@gmail.com>

#需要 sudo apt-get install python-xlib -y

try:
	import Xlib
except:
	import os
	print "Run 'sudo apt-get install python-xlib -y'"
	os.system('sudo apt-get install python-xlib -y')
	try:
		import Xlib
	except:
		sys.exit(0)
import Xlib.display
import Xlib.X
import Xlib.XK
import Xlib.protocol.event
import Xlib.ext.xtest

display = Xlib.display.Display()

special_X_keysyms = {
	' ' : "space",
	'\t' : "Tab",
	'\n' : "Return",  # for some reason this needs to be cr, not lf
	'\r' : "Return",
	'\e' : "Escape",
	'!' : "exclam",
	'#' : "numbersign",
	'%' : "percent",
	'$' : "dollar",
	'&' : "ampersand",
	'"' : "quotedbl",
	'\'' : "apostrophe",
	'(' : "parenleft",
	')' : "parenright",
	'*' : "asterisk",
	'=' : "equal",
	'+' : "plus",
	',' : "comma",
	'-' : "minus",
	'.' : "period",
	'/' : "slash",
	':' : "colon",
	';' : "semicolon",
	'<' : "less",
	'>' : "greater",
	'?' : "question",
	'@' : "at",
	'[' : "bracketleft",
	']' : "bracketright",
	'\\' : "backslash",
	'^' : "asciicircum",
	'_' : "underscore",
	'`' : "grave",
	'{' : "braceleft",
	'|' : "bar",
	'}' : "braceright",
	'~' : "asciitilde"
}


def get_keysym(ch) :
	keysym = Xlib.XK.string_to_keysym(ch)
	if keysym == 0 :
		# Unfortunately, although this works to get the correct keysym
		# i.e. keysym for '#' is returned as "numbersign"
		# the subsequent display.keysym_to_keycode("numbersign") is 0.
		keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])
	return keysym

def char_to_keycode(ch) :
	keysym = get_keysym(ch)
#	print keysym
	keycode = display.keysym_to_keycode(keysym)
#	if keycode == 0 :
#		print "Sorry, can't map", ch
#	print keycode
	return keycode

ctrlkey=display.keysym_to_keycode(Xlib.XK.XK_Control_L)
altkey=display.keysym_to_keycode(Xlib.XK.XK_Alt_L)
shiftkey=display.keysym_to_keycode(Xlib.XK.XK_Shift_L)

def sendkey(keystroke):
	ctrl = alt = shift = 0
	key = ""
	splitted = keystroke.split(" ")
	for stroke in splitted:
		if stroke == "Ctrl":
			ctrl = 1
		elif stroke == "Shift":
			shift = 1
		elif stroke == "Alt":
			alt = 1
		elif stroke == "Space": 
			key = char_to_keycode(" ")
		else: # an ordinary key
			key = char_to_keycode(stroke)
	if ctrl==1:
		Xlib.ext.xtest.fake_input(display, Xlib.X.KeyPress, ctrlkey)
	if alt==1:
		Xlib.ext.xtest.fake_input(display, Xlib.X.KeyPress, altkey)
	if shift==1:
		Xlib.ext.xtest.fake_input(display, Xlib.X.KeyPress, shiftkey)
	Xlib.ext.xtest.fake_input(display, Xlib.X.KeyPress, key)
	Xlib.ext.xtest.fake_input(display, Xlib.X.KeyRelease, key)
	if ctrl==1:
		Xlib.ext.xtest.fake_input(display, Xlib.X.KeyRelease, ctrlkey)
	if alt==1:
		Xlib.ext.xtest.fake_input(display, Xlib.X.KeyRelease, altkey)
	if shift==1:
		Xlib.ext.xtest.fake_input(display, Xlib.X.KeyRelease, shiftkey)
	display.sync()

# Example
# sendkey('Alt Tab')
# sendkey('Space')
# 注意区别：
# sendkey('Ctrl A') #Ctrl a
# sendkey('Ctrl Shift A') #Ctrl A

# 以下代码在有些机器上导致段错误。所以以下代码不再使用 -_-b
#import virtkey
#import gtk
#v = virtkey.virtkey()
#
# from gestikk (https://launchpad.net/gestikk)
#def parsekeystroke(keystroke):
#	modifiers = 0
#	key = ""
#	splitted = keystroke.split(" ")
#	for stroke in splitted:
#		if stroke == "Ctrl":
#			modifiers |= (1 << 2)
#		elif stroke == "Shift":
#			modifiers |= (1 << 0)
#		elif stroke == "Alt":
#			modifiers |= (1 << 3)
#		else: # an ordinary key
#			key = gtk.gdk.keyval_from_name(stroke)
#	return (modifiers, key)
#
# from gestikk (https://launchpad.net/gestikk)
#def sendkey(keystroke):
#	global v
#	modifiers, key = parsekeystroke(keystroke)
#	if modifiers:
#		v.latch_mod(modifiers)
#	v.press_keysym(key)
#	v.release_keysym(key)
#	if modifiers:
#		v.unlatch_mod(modifiers)
